home *** CD-ROM | disk | FTP | other *** search
/ Komputer for Alle 1999 #5 / 1999 CD 5 (black).iso / Delphi3 / install / data.z / COLORGRD.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1997-08-05  |  16.5 KB  |  547 lines

  1.  
  2. {*******************************************************}
  3. {                                                       }
  4. {       Delphi Visual Component Library                 }
  5. {                                                       }
  6. {       Copyright (c) 1995,97 Borland International     }
  7. {                                                       }
  8. {*******************************************************}
  9.  
  10. unit ColorGrd;
  11.  
  12. {$R-}
  13.  
  14. interface
  15.  
  16. uses Windows, Messages, Classes, Graphics, Forms, Controls, ExtCtrls;
  17.  
  18. const
  19.   NumPaletteEntries = 20;
  20.  
  21. type
  22.   TGridOrdering = (go16x1, go8x2, go4x4, go2x8, go1x16);
  23.  
  24.   TColorGrid = class(TCustomControl)
  25.   private
  26.     FPaletteEntries: array[0..NumPaletteEntries - 1] of TPaletteEntry;
  27.     FClickEnablesColor: Boolean;
  28.     FForegroundIndex: Integer;
  29.     FBackgroundIndex: Integer;
  30.     FForegroundEnabled: Boolean;
  31.     FBackgroundEnabled: Boolean;
  32.     FSelection: Integer;
  33.     FCellXSize, FCellYSize: Integer;
  34.     FNumXSquares, FNumYSquares: Integer;
  35.     FGridOrdering: TGridOrdering;
  36.     FHasFocus: Boolean;
  37.     FOnChange: TNotifyEvent;
  38.     FButton: TMouseButton;
  39.     FButtonDown: Boolean;
  40.     procedure DrawSquare(Which: Integer; ShowSelector: Boolean);
  41.     procedure DrawFgBg;
  42.     procedure UpdateCellSizes(DoRepaint: Boolean);
  43.     procedure SetGridOrdering(Value: TGridOrdering);
  44.     function GetForegroundColor: TColor;
  45.     function GetBackgroundColor: TColor;
  46.     procedure SetForegroundIndex(Value: Integer);
  47.     procedure SetBackgroundIndex(Value: Integer);
  48.     procedure SetSelection(Value: Integer);
  49.     procedure EnableForeground(Value: Boolean);
  50.     procedure EnableBackground(Value: Boolean);
  51.     procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;
  52.     procedure WMKillFocus(var Message: TWMKillFocus); message WM_KILLFOCUS;
  53.     procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
  54.     procedure WMSize(var Message: TWMSize); message WM_SIZE;
  55.     procedure CMCtl3DChanged(var Message: TMessage); message CM_CTL3DCHANGED;
  56.   protected
  57.     procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  58.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
  59.       X, Y: Integer); override;
  60.     procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  61.     procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
  62.       X, Y: Integer); override;
  63.     procedure CreateWnd; override;
  64.     procedure Paint; override;
  65.     procedure Change; dynamic;
  66.     function SquareFromPos(X, Y: Integer): Integer;
  67.   public
  68.     constructor Create(AOwner: TComponent); override;
  69.     function ColorToIndex(AColor: TColor): Integer;
  70.     property ForegroundColor: TColor read GetForegroundColor;
  71.     property BackgroundColor: TColor read GetBackgroundColor;
  72.   published
  73.     property ClickEnablesColor: Boolean read FClickEnablesColor write FClickEnablesColor default False;
  74.     property Ctl3D;
  75.     property DragCursor;
  76.     property DragMode;
  77.     property Enabled;
  78.     property GridOrdering: TGridOrdering read FGridOrdering write SetGridOrdering default go4x4;
  79.     property ForegroundIndex: Integer read FForegroundIndex write SetForegroundIndex default 0;
  80.     property BackgroundIndex: Integer read FBackgroundIndex write SetBackgroundIndex default 0;
  81.     property ForegroundEnabled: Boolean read FForegroundEnabled write EnableForeground default True;
  82.     property BackgroundEnabled: Boolean read FBackgroundEnabled write EnableBackground default True;
  83.     property Font;
  84.     property ParentCtl3D;
  85.     property ParentFont;
  86.     property ParentShowHint;
  87.     property PopUpMenu;
  88.     property Selection: Integer read FSelection write SetSelection default 0;
  89.     property ShowHint;
  90.     property TabOrder;
  91.     property TabStop;
  92.     property Visible;
  93.     property OnChange: TNotifyEvent read FOnChange write FOnChange;
  94.     property OnClick;
  95.     property OnDragDrop;
  96.     property OnDragOver;
  97.     property OnEndDrag;
  98.     property OnEnter;
  99.     property OnExit;
  100.     property OnKeyDown;
  101.     property OnKeyPress;
  102.     property OnKeyUp;
  103.     property OnMouseDown;
  104.     property OnMouseMove;
  105.     property OnMouseUp;
  106.     property OnStartDrag;
  107.   end;
  108.  
  109. implementation
  110.  
  111. uses SysUtils, Consts, StdCtrls;
  112.  
  113. constructor TColorGrid.Create(AOwner: TComponent);
  114. begin
  115.   inherited Create(AOwner);
  116.   ControlStyle := ControlStyle + [csOpaque];
  117.   FGridOrdering := go4x4;
  118.   FNumXSquares := 4;
  119.   FNumYSquares := 4;
  120.   FForegroundEnabled := True;
  121.   FBackgroundEnabled := True;
  122.   Color := clBtnFace;
  123.   Canvas.Brush.Style := bsSolid;
  124.   Canvas.Pen.Color := clBlack;
  125.   SetBounds(0, 0, 100, 100);
  126.   GetPaletteEntries(GetStockObject(DEFAULT_PALETTE), 0, NumPaletteEntries,
  127.     FPaletteEntries);
  128. end;
  129.  
  130. function TColorGrid.ColorToIndex(AColor: TColor): Integer;
  131. var
  132.   I: Integer;
  133.   RealColor: TColor;
  134. begin
  135.   Result := 0;
  136.   I := 0;
  137.   RealColor := ColorToRGB(AColor);
  138.   while I < 20 do
  139.   begin
  140.     with FPaletteEntries[I] do
  141.       if RealColor = RGB(peRed, peGreen, peBlue) then Exit;
  142.     if (I < 8) or (I > 8) then
  143.       Inc(I) else Inc(I, 4);
  144.     Inc(Result);
  145.   end;
  146.   Result := -1;    
  147. end;
  148.  
  149. procedure TColorGrid.CreateWnd;
  150. begin
  151.   inherited CreateWnd;
  152.   SetWindowLong(Handle, GWL_STYLE, GetWindowLong(Handle, GWL_STYLE)
  153.     or WS_CLIPSIBLINGS);
  154. end;
  155.  
  156. procedure TColorGrid.DrawSquare(Which: Integer; ShowSelector: Boolean);
  157. var
  158.   WinTop, WinLeft: Integer;
  159.   PalIndex: Integer;
  160.   CellRect: TRect;
  161. begin
  162.   if (Which >=0) and (Which <= 15) then
  163.   begin
  164.     if Which < 8 then
  165.       PalIndex := Which else PalIndex := Which + 4;
  166.     WinTop := (Which div FNumXSquares) * FCellYSize;
  167.     WinLeft := (Which mod FNumXSquares) * FCellXSize;
  168.     CellRect := Bounds(WinLeft, WinTop, FCellXSize, FCellYSize);
  169.     if Ctl3D then
  170.     begin
  171.       Canvas.Pen.Color := clBtnFace;
  172.       with CellRect do Canvas.Rectangle(Left, Top, Right, Bottom);
  173.       InflateRect(CellRect, -1, -1);
  174.       Frame3D(Canvas, CellRect, clBtnShadow, clBtnHighlight, 2);
  175.     end else Canvas.Pen.Color := clBlack;
  176.     with FPaletteEntries[PalIndex] do
  177.     begin
  178.       Canvas.Brush.Color := TColor(RGB(peRed, peGreen, peBlue));
  179.       if Ctl3D then Canvas.Pen.Color := TColor(RGB(peRed, peGreen, peBlue));
  180.     end;
  181.     if not ShowSelector then with CellRect do
  182.       Canvas.Rectangle(Left, Top, Right, Bottom)
  183.     else with CellRect do
  184.     begin
  185.       if Ctl3D then
  186.       begin
  187.         Canvas.Rectangle(Left, Top, Right, Bottom);
  188.         InflateRect(CellRect, -1, -1);
  189.         DrawFocusRect(Canvas.Handle, CellRect);
  190.       end else with Canvas do
  191.       begin
  192.         Pen.Color := clBlack;
  193.         Pen.Mode := pmNot;
  194.         Rectangle(Left, Top, Right, Bottom);
  195.         Pen.Mode := pmCopy;
  196.         Rectangle(Left + 2, Top + 2, Right - 2, Bottom - 2);
  197.       end;
  198.     end;
  199.   end;
  200. end;
  201.  
  202. procedure TColorGrid.DrawFgBg;
  203. var
  204.   TextColor: TPaletteEntry;
  205.   PalIndex: Integer;
  206.   TheText: string;
  207.   OldBkMode: Integer;
  208.   R: TRect;
  209.  
  210.   function TernaryOp(Test: Boolean; ResultTrue, ResultFalse: Integer): Integer;
  211.   begin
  212.     if Test then
  213.       Result := ResultTrue
  214.     else Result := ResultFalse;
  215.   end;
  216.  
  217. begin
  218.   OldBkMode := SetBkMode(Canvas.Handle, TRANSPARENT);
  219.   if FForegroundEnabled then
  220.   begin
  221.     if (FForegroundIndex = FBackgroundIndex) and FBackgroundEnabled then
  222.       TheText := SFB else TheText := SFG;
  223.     if FForegroundIndex < 8 then
  224.       PalIndex := FForegroundIndex else PalIndex := FForegroundIndex + 4;
  225.     TextColor := FPaletteEntries[PalIndex];
  226.     with TextColor do
  227.     begin
  228.       peRed := TernaryOp(peRed >= $80, 0, $FF);
  229.       peGreen := TernaryOp(peGreen >= $80, 0, $FF);
  230.       peBlue := TernaryOp(peBlue >= $80, 0, $FF);
  231.       Canvas.Font.Color := TColor(RGB(peRed, peGreen, peBlue));
  232.     end;
  233.     with R do
  234.     begin
  235.       left := (FForegroundIndex mod FNumXSquares) * FCellXSize;
  236.       right := left + FCellXSize;
  237.       top := (FForegroundIndex div FNumXSquares) * FCellYSize;
  238.       bottom := top + FCellYSize;
  239.     end;
  240.     DrawText(Canvas.Handle, PChar(TheText), -1, R,
  241.        DT_NOCLIP or DT_SINGLELINE or DT_CENTER or DT_VCENTER);
  242.   end;
  243.   if FBackgroundEnabled then
  244.   begin
  245.     if (FForegroundIndex = FBackgroundIndex) and FForegroundEnabled then
  246.       TheText := SFB else TheText := SBG;
  247.     if FBackgroundIndex < 8 then
  248.       PalIndex := FBackgroundIndex else PalIndex := FBackgroundIndex + 4;
  249.     TextColor := FPaletteEntries[PalIndex];
  250.     with TextColor do
  251.     begin
  252.       peRed := TernaryOp(peRed >= $80, 0, $FF);
  253.       peGreen := TernaryOp(peGreen >= $80, 0, $FF);
  254.       peBlue := TernaryOp(peBlue >= $80, 0, $FF);
  255.       Canvas.Font.Color := TColor(RGB(peRed, peGreen, peBlue));
  256.     end;
  257.     with R do
  258.     begin
  259.       left := (FBackgroundIndex mod FNumXSquares) * FCellXSize;
  260.       right := left + FCellXSize;
  261.       top := (FBackgroundIndex div FNumXSquares) * FCellYSize;
  262.       bottom := top + FCellYSize;
  263.     end;
  264.     DrawText(Canvas.Handle, PChar(TheText), -1, R,
  265.       DT_NOCLIP or DT_SINGLELINE or DT_CENTER or DT_VCENTER);
  266.   end;
  267.   SetBkMode(Canvas.Handle, OldBkMode);
  268. end;
  269.  
  270. procedure TColorGrid.EnableForeground(Value: Boolean);
  271. begin
  272.   if FForegroundEnabled = Value then Exit;
  273.   FForegroundEnabled := Value;
  274.   DrawSquare(FForegroundIndex, (FForegroundIndex = FSelection) and FHasFocus);
  275.   DrawFgBg;
  276. end;
  277.  
  278. procedure TColorGrid.EnableBackground(Value: Boolean);
  279. begin
  280.   if FBackgroundEnabled = Value then Exit;
  281.   FBackgroundEnabled := Value;
  282.   DrawSquare(FBackgroundIndex, (FBackgroundIndex = FSelection) and FHasFocus);
  283.   DrawFgBg;
  284. end;
  285.  
  286. function TColorGrid.GetForegroundColor: TColor;
  287. var
  288.   PalIndex: Integer;
  289. begin
  290.   if FForegroundIndex < 8 then
  291.     PalIndex := FForegroundIndex else PalIndex := FForegroundIndex + 4;
  292.   with FPaletteEntries[PalIndex] do
  293.     Result := TColor(RGB(peRed, peGreen, peBlue));
  294. end;
  295.  
  296. function TColorGrid.GetBackgroundColor: TColor;
  297. var
  298.   PalIndex: Integer;
  299. begin
  300.   if FBackgroundIndex < 8 then
  301.     PalIndex := FBackgroundIndex else PalIndex := FBackgroundIndex + 4;
  302.   with FPaletteEntries[PalIndex] do
  303.     Result := TColor(RGB(peRed, peGreen, peBlue));
  304. end;
  305.  
  306. procedure TColorGrid.WMSetFocus(var Message: TWMSetFocus);
  307. begin
  308.   FHasFocus := True;
  309.   DrawSquare(FSelection, True);
  310.   DrawFgBg;
  311.   inherited;
  312. end;
  313.  
  314. procedure TColorGrid.WMKillFocus(var Message: TWMKillFocus);
  315. begin
  316.   FHasFocus := False;
  317.   DrawSquare(FSelection, False);
  318.   DrawFgBg;
  319.   inherited;
  320. end;
  321.  
  322. procedure TColorGrid.KeyDown(var Key: Word; Shift: TShiftState);
  323. var
  324.   NewSelection: Integer;
  325.   Range: Integer;
  326. begin
  327.   inherited KeyDown(Key, Shift);
  328.   NewSelection := FSelection;
  329.   Range := FNumXSquares * FNumYSquares;
  330.   case Key of
  331.     $46, $66:
  332.       begin
  333.         if not FForegroundEnabled and FClickEnablesColor then
  334.         begin
  335.           FForegroundEnabled := True;
  336.           DrawSquare(FForegroundIndex, (FForegroundIndex = FSelection) and FHasFocus);
  337.           FForegroundIndex := -1;
  338.         end;
  339.         SetForegroundIndex(NewSelection);
  340.         SetSelection(NewSelection);
  341.         Click;
  342.       end;
  343.     $42, $62:
  344.       begin
  345.         if not FBackgroundEnabled and FClickEnablesColor then
  346.         begin
  347.           FBackgroundEnabled := True;
  348.           DrawSquare(FBackgroundIndex, (FBackgroundIndex = FSelection) and FHasFocus);
  349.           FBackgroundIndex := -1;
  350.         end;
  351.         SetBackgroundIndex(NewSelection);
  352.         SetSelection(NewSelection);
  353.         Click;
  354.       end;
  355.     VK_HOME: NewSelection := 0;
  356.     VK_UP:
  357.       if FSelection >= FNumXSquares then
  358.         NewSelection := FSelection - FNumXSquares
  359.       else if FSelection <> 0 then
  360.         NewSelection := Range - FNumXSquares + FSelection - 1
  361.       else NewSelection := Range - 1;
  362.     VK_LEFT:
  363.       if FSelection <> 0 then
  364.         NewSelection := FSelection - 1
  365.       else NewSelection := Range - 1;
  366.     VK_DOWN:
  367.       if FSelection + FNumXSquares < Range then
  368.         NewSelection := FSelection + FNumXSquares
  369.       else if FSelection <> Range - 1 then
  370.         NewSelection := FSelection mod FNumXSquares + 1
  371.       else NewSelection := 0;
  372.     VK_SPACE,
  373.     VK_RIGHT:
  374.       if FSelection <> Range - 1 then
  375.         NewSelection := FSelection + 1
  376.       else NewSelection := 0;
  377.     VK_END: NewSelection := Range - 1;
  378.   else
  379.     inherited KeyDown(Key, Shift);
  380.     Exit;
  381.   end;
  382.   Key := 0;
  383.   if FSelection <> NewSelection then
  384.     SetSelection(NewSelection);
  385. end;
  386.  
  387. procedure TColorGrid.WMGetDlgCode(var Message: TWMGetDlgCode);
  388. begin
  389.   Message.Result := DLGC_WANTARROWS + DLGC_WANTCHARS;
  390. end;
  391.  
  392. procedure TColorGrid.WMSize(var Message: TWMSize);
  393. begin
  394.   inherited;
  395.   UpdateCellSizes(False);
  396. end;
  397.  
  398. procedure TColorGrid.CMCtl3DChanged(var Message: TMessage);
  399. begin
  400.   inherited;
  401.   Invalidate;
  402. end;
  403.  
  404. procedure TColorGrid.MouseDown(Button: TMouseButton; Shift: TShiftState;
  405.   X, Y: Integer);
  406. var
  407.   Square: Integer;
  408. begin
  409.   inherited MouseDown(Button, Shift, X, Y);
  410.   FButton := Button;
  411.   FButtonDown := True;
  412.   Square := SquareFromPos(X, Y);
  413.   if Button = mbLeft then
  414.   begin
  415.     if not FForegroundEnabled and FClickEnablesColor then
  416.     begin
  417.       FForegroundEnabled := True;
  418.       DrawSquare(FForegroundIndex, (FForegroundIndex = FSelection) and FHasFocus);
  419.       FForegroundIndex := -1;
  420.     end;
  421.     SetForegroundIndex(Square);
  422.   end
  423.   else begin
  424.     MouseCapture := True;
  425.     if not FBackgroundEnabled and FClickEnablesColor then
  426.     begin
  427.       FBackgroundEnabled := True;
  428.       DrawSquare(FBackgroundIndex, (FBackgroundIndex = FSelection) and FHasFocus);
  429.       FBackgroundIndex := -1;
  430.     end;
  431.     SetBackgroundIndex(Square);
  432.   end;
  433.   SetSelection(Square);
  434.   if TabStop then SetFocus;
  435. end;
  436.  
  437. procedure TColorGrid.MouseMove(Shift: TShiftState; X, Y: Integer);
  438. var
  439.   Square: Integer;
  440. begin
  441.   inherited MouseMove(Shift, X, Y);
  442.   if FButtonDown then
  443.   begin
  444.     Square := SquareFromPos(X, Y);
  445.     if FButton = mbLeft then
  446.       SetForegroundIndex(Square)
  447.     else SetBackgroundIndex(Square);
  448.     SetSelection(Square);
  449.   end;
  450. end;
  451.  
  452. procedure TColorGrid.MouseUp(Button: TMouseButton; Shift: TShiftState;
  453.   X, Y: Integer);
  454. begin
  455.   inherited MouseUp(Button, Shift, X, Y);
  456.   FButtonDown := False;
  457.   if FButton = mbRight then MouseCapture := False;
  458. end;
  459.  
  460. procedure TColorGrid.Paint;
  461. var
  462.   Row, Col, wEntryIndex: Integer;
  463. begin
  464.   Canvas.Font := Font;
  465.   for Row := 0 to FNumYSquares do
  466.     for Col := 0 to FNumXSquares do
  467.     begin
  468.       wEntryIndex := Row * FNumXSquares + Col;
  469.       DrawSquare(wEntryIndex, False);
  470.     end;
  471.   DrawSquare(FSelection, FHasFocus);
  472.   DrawFgBg;
  473. end;
  474.  
  475. procedure TColorGrid.SetBackgroundIndex(Value: Integer);
  476. begin
  477.   if (FBackgroundIndex <> Value) and FBackgroundEnabled then
  478.   begin
  479.     DrawSquare(FBackgroundIndex, (FBackgroundIndex = FSelection) and FHasFocus);
  480.     FBackgroundIndex := Value;
  481.     if FBackgroundIndex = FForegroundIndex then
  482.       DrawSquare(FBackgroundIndex, (FBackgroundIndex = FSelection) and FHasFocus);
  483.     DrawFgBg;
  484.     Change;
  485.   end;
  486. end;
  487.  
  488. procedure TColorGrid.SetForegroundIndex(Value: Integer);
  489. begin
  490.   if (FForegroundIndex <> Value) and FForegroundEnabled then
  491.   begin
  492.     DrawSquare(FForegroundIndex, (FForegroundIndex = FSelection) and FHasFocus);
  493.     FForegroundIndex := Value;
  494.     if FForegroundIndex = FBackgroundIndex then
  495.       DrawSquare(FForegroundIndex, (FForegroundIndex = FSelection) and FHasFocus);
  496.     DrawFgBg;
  497.     Change;
  498.   end;
  499. end;
  500.  
  501. procedure TColorGrid.SetGridOrdering(Value: TGridOrdering);
  502. begin
  503.   if FGridOrdering = Value then Exit;
  504.   FGridOrdering := Value;
  505.   FNumXSquares := 16 shr Ord(FGridOrdering);
  506.   FNumYSquares := 1 shl Ord(FGridOrdering);
  507.   UpdateCellSizes(True);
  508. end;
  509.  
  510. procedure TColorGrid.SetSelection(Value: Integer);
  511. begin
  512.   if FSelection = Value then Exit;
  513.   DrawSquare(FSelection, False);
  514.   FSelection := Value;
  515.   DrawSquare(FSelection, FHasFocus);
  516.   DrawFgBg;
  517. end;
  518.  
  519. function TColorGrid.SquareFromPos(X, Y: Integer): Integer;
  520. begin
  521.   if X > Width - 1 then X := Width - 1
  522.   else if X < 0 then X := 0;
  523.   if Y > Height - 1 then Y := Height - 1
  524.   else if Y < 0 then Y := 0;
  525.   Result := (Y div FCellYSize) * FNumXSquares + (X div FCellXSize);
  526. end;
  527.  
  528. procedure TColorGrid.UpdateCellSizes(DoRepaint: Boolean);
  529. var
  530.   NewWidth, NewHeight: Integer;
  531. begin
  532.   NewWidth := (Width div FNumXSquares) * FNumXSquares;
  533.   NewHeight := (Height div FNumYSquares) * FNumYSquares;
  534.   BoundsRect := Bounds(Left, Top, NewWidth, NewHeight);
  535.   FCellXSize := Width div FNumXSquares;
  536.   FCellYSize := Height div FNumYSquares;
  537.   if DoRepaint then Invalidate;
  538. end;
  539.  
  540. procedure TColorGrid.Change;
  541. begin
  542.   Changed;
  543.   if Assigned(FOnChange) then FOnChange(Self);
  544. end;
  545.  
  546. end.
  547.